home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / emacs-complete / fsf / emacs / lwlib / lwlib-xolmb.c < prev    next >
C/C++ Source or Header  |  1994-01-18  |  9KB  |  371 lines

  1. /* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
  2.    Copyright (C) 1993 Lucid, Inc.
  3.  
  4. This file is part of the Lucid Widget Library.
  5.  
  6. The Lucid Widget Library is free software; you can redistribute it and/or 
  7. modify it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. The Lucid Widget Library is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <X11/IntrinsicP.h>
  21. #include <X11/Intrinsic.h>
  22. #include <X11/CompositeP.h>
  23. #include <X11/Composite.h>
  24. #include "lwlib-Xol-mbP.h"
  25. #include "lwlib-Xol-mb.h"
  26.  
  27. #define HORIZ_SPACING    4
  28. #define VERT_SPACING    4
  29.  
  30. static void        Initialize();
  31. static void        Resize();
  32. static void        ChangeManaged();
  33. static Boolean        SetValues();
  34. static XtGeometryResult    GeometryManager();
  35. static XtGeometryResult    PreferredSize();
  36. static void        do_layout();
  37. static XtGeometryResult try_layout();
  38.  
  39. lwMenuBarClassRec lwMenubarClassRec = 
  40. {
  41.   {
  42.     /* core_class members */
  43.     
  44.     (WidgetClass) &compositeClassRec,    /* superclass            */
  45.     "Menubar",                /* class_name            */
  46.     sizeof(lwMenuBarRec),        /* widget_size            */
  47.     NULL,                /* class_initialize        */
  48.     NULL,                /* class_part_initialize    */
  49.     FALSE,                /* class_inited            */
  50.     Initialize,                /* initialize            */
  51.     NULL,                /* initialize_hook        */
  52.     XtInheritRealize,            /* realize            */
  53.     NULL,                /* actions            */
  54.     0,                    /* num_actions            */
  55.     NULL,                /* resources            */
  56.     0,                    /* num_resources        */
  57.     NULLQUARK,                /* xrm_class            */
  58.     TRUE,                /* compress_motion        */
  59.     XtExposeCompressMaximal,        /* compress_exposure        */
  60.     TRUE,                /* compress_enterleave        */
  61.     FALSE,                /* visible_interest        */
  62.     NULL,                /* destroy            */
  63.     Resize,                /* resize            */
  64.     NULL,                /* expose            */
  65.     NULL,                /* set_values            */
  66.     NULL,                /* set_values_hook        */
  67.     XtInheritSetValuesAlmost,        /* set_values_almost        */
  68.     NULL,                /* get_values_hook        */
  69.     NULL,                /* accept_focus            */
  70.     XtVersion,                /* version            */
  71.     NULL,                /* callback_private        */
  72.     NULL,                /* tm_table            */
  73.     PreferredSize,            /* query_geometry        */
  74.     NULL,                /* display_accelerator        */
  75.     NULL,                /* extension            */
  76.   },
  77.   {
  78.     /* composite_class members */
  79.     
  80.     GeometryManager,            /* geometry_manager        */
  81.     ChangeManaged,            /* change_managed        */
  82.     XtInheritInsertChild,        /* insert_child            */
  83.     XtInheritDeleteChild,        /* delete_child            */
  84.     NULL,                /* extension            */
  85.   },
  86.   {
  87.     /* Menubar class members */
  88.     
  89.     0,                    /* empty            */
  90.   }
  91. };
  92. WidgetClass lwMenubarWidgetClass = (WidgetClass) &lwMenubarClassRec;
  93.  
  94.  
  95. static void Initialize (request, new)
  96.      lwMenuBarWidget    request, new;
  97. {
  98.   if (request->core.width <= 0)
  99.     new->core.width = 1;
  100.   if (request->core.height <= 0)
  101.     new->core.height = 23;
  102. }
  103.  
  104. static void
  105. Resize (w)
  106.      lwMenuBarWidget    w;
  107. {
  108.   do_layout(w);
  109. }
  110.  
  111. static void
  112. do_layout (parent)
  113.      lwMenuBarWidget parent;
  114. {
  115.   Widget    child;
  116.   int        cnt;
  117.   int        managed_children = 0;
  118.   int        managed_width = 0;
  119.   int        new_pos = 0;
  120.  
  121.   /*
  122.    * Determine number of children which will fit on one line.
  123.    * For now we ignore the rest, making sure they are unmanaged.
  124.    */
  125.  
  126.   cnt = 0;
  127.   while ((cnt < (int) parent->composite.num_children) &&
  128.      (managed_width < (int) parent->core.width))
  129.     {
  130.       child = parent->composite.children[cnt++];
  131.       managed_children++;
  132.       managed_width += child->core.width + child->core.border_width * 2 +
  133.     HORIZ_SPACING;
  134.     }
  135.   
  136.   if (managed_width > (int) parent->core.width)
  137.     managed_children--;
  138.   
  139.   /*
  140.    * Correct positioning of children.
  141.    */
  142.  
  143.   cnt = 0;
  144.   while (managed_children)
  145.     {
  146.       child = parent->composite.children[cnt++];
  147.  
  148.       if (!child->core.managed)
  149.     XtManageChild (child);
  150.  
  151.       if ((child->core.x != new_pos) || (child->core.y != 0))
  152.     XtMoveWidget (child, new_pos, 0);
  153.       new_pos += child->core.width + child->core.border_width * 2 +
  154.     HORIZ_SPACING;
  155.  
  156.       managed_children--;
  157.     }
  158.   
  159.   /*
  160.    * Make sure all remaining children are unmanaged.
  161.    */
  162.  
  163.   while (cnt < parent->composite.num_children)
  164.     {
  165.       child = parent->composite.children[cnt];
  166.       
  167.       if (child->core.managed)
  168.     XtUnmanageChild (child);
  169.  
  170.       if ((child->core.x != parent->core.width) || 
  171.       (child->core.y != parent->core.height))
  172.     XtMoveWidget (child, parent->core.width, parent->core.height);
  173.  
  174.       cnt++;
  175.     }
  176. }
  177.  
  178.  
  179. static XtGeometryResult
  180. PreferredSize (w, request, preferred)
  181.      lwMenuBarWidget    w;
  182.      XtWidgetGeometry    *request, *preferred;
  183. {
  184.   Widget    child;
  185.   int        cnt;
  186.  
  187.   /*
  188.    * If no changes are being made to the width or height, just agree.
  189.    */
  190.  
  191.   if (!(request->request_mode & CWWidth) &&
  192.       !(request->request_mode & CWHeight))
  193.     return (XtGeometryYes);
  194.   
  195.   /*
  196.    * Right now assume everything goes in one row.  Calculate the
  197.    * minimum required width and height.
  198.    */
  199.  
  200.   preferred->width = 0;
  201.   preferred->height = 0;
  202.   
  203.   for (cnt = 0; cnt < w->composite.num_children; cnt++)
  204.     {
  205.       child = w->composite.children[cnt];
  206.       if (child->core.managed)
  207.     {
  208.       preferred->width += child->core.width + child->core.border_width*2 +
  209.         HORIZ_SPACING;
  210.       if (preferred->height < (Dimension) (child->core.height +
  211.           child->core.border_width * 2))
  212.         preferred->height = child->core.height +
  213.           child->core.border_width * 2;
  214.     }
  215.     }
  216.   
  217.   preferred->request_mode = CWWidth | CWHeight;
  218.  
  219.   /*
  220.    * Case:  both height and width requested
  221.    */
  222.  
  223.   if ((request->request_mode & CWWidth) &&
  224.       (request->request_mode & CWHeight))
  225.     {
  226.       /*
  227.        * Ok if same or bigger.
  228.        */
  229.  
  230.       if (preferred->width <= request->width &&
  231.       preferred->height <= request->height)
  232.     {
  233.       preferred->width = request->width;
  234.       return (XtGeometryYes);
  235.     }
  236.       
  237.       /*
  238.        * If both dimensions are too small, say no.
  239.        */
  240.  
  241.       else
  242.     if (preferred->width > request->width &&
  243.         preferred->height > request->height)
  244.       return (XtGeometryNo);
  245.       
  246.       /*
  247.        * Otherwise one must be right, so say almost.
  248.        */
  249.  
  250.       else
  251.     return (XtGeometryAlmost);
  252.     }
  253.   
  254.   /*
  255.    * If only one dimension is requested, either its OK or it isn't.
  256.    */
  257.  
  258.   else
  259.     {
  260.       if (request->request_mode & CWWidth)
  261.     {
  262.       if (preferred->width <= request->width)
  263.         {
  264.           preferred->width = request->width;
  265.           return (XtGeometryYes);
  266.         }
  267.       else
  268.         return (XtGeometryNo);
  269.     }
  270.       else if (request->request_mode & CWHeight)
  271.     {
  272.       if (preferred->height <= request->height)
  273.         {
  274.           return (XtGeometryYes);
  275.         }
  276.       else
  277.         return (XtGeometryNo);
  278.     }
  279.  
  280.       return (XtGeometryYes);
  281.     }
  282. }
  283.   
  284.  
  285. static XtGeometryResult
  286. GeometryManager (w, request, reply)
  287.      Widget        w;
  288.      XtWidgetGeometry    *request;
  289.      XtWidgetGeometry    *reply;
  290. {
  291.   
  292.   lwMenuBarWidget    parent = (lwMenuBarWidget) w->core.parent;
  293.   
  294.   /*
  295.    * If the widget wants to move, just say no.
  296.    */
  297.  
  298.   if ((request->request_mode & CWX && request->x != w->core.x) ||
  299.    (request->request_mode & CWY && request->y != w->core.y))
  300.     return (XtGeometryNo);
  301.   
  302.   /*
  303.    * Since everything "fits" for now, grant all requests.
  304.    */
  305.  
  306.   if (request->request_mode & CWWidth)
  307.     w->core.width = request->width;
  308.   if (request->request_mode & CWHeight)
  309.     w->core.height = request->height;
  310.   if (request->request_mode & CWBorderWidth)
  311.     w->core.border_width = request->border_width;
  312.   
  313.   do_layout (parent);
  314.   return (XtGeometryYes);
  315. }
  316.  
  317.  
  318. static XtGeometryResult
  319. try_layout (parent)
  320.      lwMenuBarWidget parent;
  321. {
  322.   Widget    child;
  323.   int        cnt;
  324.   int        managed_children = 0;
  325.   int        managed_width = 0;
  326.   int        new_pos = 0;
  327.  
  328.   /*
  329.    * Determine number of children which will fit on one line.
  330.    * For now we ignore the rest, making sure they are unmanaged.
  331.    */
  332.  
  333.   cnt = 0;
  334.   while ((cnt < (int) parent->composite.num_children) &&
  335.      (managed_width < (int) parent->core.width))
  336.     {
  337.       child = parent->composite.children[cnt++];
  338.       if (child->core.managed)
  339.     {
  340.       managed_children++;
  341.       managed_width += child->core.width + child->core.border_width * 2 +
  342.         HORIZ_SPACING;
  343.     }
  344.     }
  345.  
  346.   if (managed_width > (int) parent->core.width)
  347.     return (XtGeometryNo);
  348.   else
  349.     return (XtGeometryYes);
  350. }
  351.  
  352.  
  353.      
  354. static void
  355. ChangeManaged (w)
  356.      lwMenuBarWidget    w;
  357. {
  358.   XtGeometryResult    result;
  359.   
  360.   result = try_layout (w);
  361.  
  362.   if (result != XtGeometryYes)
  363.     {
  364.       XtUnmanageChild (w->composite.children[w->composite.num_children - 1]);
  365.       XtMoveWidget (w->composite.children[w->composite.num_children-1],
  366.             w->core.width, w->core.height);
  367.     }
  368.   
  369.   do_layout (w);
  370. }
  371.